package com.zdp.usercenter.auth;

import com.zdp.usercenter.security.MySecurityException;
import com.zdp.usercenter.util.JwtOperator;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @author sesshomaru
 * @date 2020/9/26 20:28
 * 1.先引入aop的依赖
 */
// aop验证用户登录授权
@Component
@Aspect
@Slf4j
public class CheckLoginAspect {

    @Autowired
    private JwtOperator jwtOperator;

    // 环绕通知 只要加了@CheckLogin都会走到这里
    @Around("@annotation(com.zdp.usercenter.auth.CheckLogin)")
    public Object checkLogin(ProceedingJoinPoint point) {
        try {
            // 1.从header里获取token
            // todo 这里还需要判断是否空指针
            // spring提供的静态方法获取request
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
            HttpServletRequest request = servletRequestAttributes.getRequest();

            String token = request.getHeader("x-token");

            // 2.校验token是否合法 & 是否过期，如果不合法或者已过期，就抛异常；如过合法就放行
            Boolean isValid = jwtOperator.validateToken(token);
            if (!isValid) {
                // 不合法抛出异常会被 (GlobalExceptionErrorHandler) 全局异常处理捕获，全局异常处理回返回对应的错误响应
                throw new MySecurityException("token不合法!");
            }

            // 合法 执行目标方法
            // 3.如果校验成功，那么就将用户的信息设置到request的attribute里面
            Claims claims = jwtOperator.getClaimsFromToken(token);
            request.setAttribute("id",claims.get("id"));
            request.setAttribute("wxNickName",claims.get("wxNickName"));
            request.setAttribute("role",claims.get("role"));

            log.info("aop验证用户登录授权成功...");
            return point.proceed();

        } catch (Throwable throwable) {
            log.warn("aop验证用户登录授权失败...");
            throw new MySecurityException("token不合法!");
        }
    }
}
